package singleton;

// Java 单例模式的四种实现方式

// 1. 饿汉式
class SingletonEager {
    // 类加载时就初始化实例
    private static final SingletonEager instance = new SingletonEager();

    // 私有构造函数，防止外部实例化
    private SingletonEager() {}

    // 提供全局访问点
    public static SingletonEager getInstance() {
        return instance;
    }
}

// 2. 懒汉式（双重检查锁）
class SingletonLazy {
    // volatile 关键字确保多线程环境下的可见性和有序性
    private static volatile SingletonLazy instance;

    // 私有构造函数
    private SingletonLazy() {}

    // 双重检查锁实现线程安全的单例
    public static SingletonLazy getInstance() {
        // 第一次检查
        if (instance == null) {
            // 加锁
            synchronized (SingletonLazy.class) {
                // 第二次检查
                if (instance == null) {
                    instance = new SingletonLazy();
                }
            }
        }
        return instance;
    }
}

// 3. 静态内部类方式
class SingletonStaticInner {
    // 私有构造函数
    private SingletonStaticInner() {}

    // 静态内部类
    private static class SingletonHolder {
        // 内部类加载时才初始化实例
        private static final SingletonStaticInner INSTANCE = new SingletonStaticInner();
    }

    // 全局访问点
    public static SingletonStaticInner getInstance() {
        return SingletonHolder.INSTANCE;
    }
}

// 4. 枚举方式（Java 专属）
enum SingletonEnum {
    // 枚举实例本身就是单例
    INSTANCE;

    // 可以添加需要的方法
    public void doSomething() {
        System.out.println("枚举单例的方法调用");
    }
}

// 测试类
public class SingletonPatterns {
    public static void main(String[] args) {
        // 测试饿汉式
        SingletonEager eager1 = SingletonEager.getInstance();
        SingletonEager eager2 = SingletonEager.getInstance();
        System.out.println("饿汉式 - 是否为同一实例: " + (eager1 == eager2));

        // 测试懒汉式
        SingletonLazy lazy1 = SingletonLazy.getInstance();
        SingletonLazy lazy2 = SingletonLazy.getInstance();
        System.out.println("懒汉式 - 是否为同一实例: " + (lazy1 == lazy2));

        // 测试静态内部类
        SingletonStaticInner static1 = SingletonStaticInner.getInstance();
        SingletonStaticInner static2 = SingletonStaticInner.getInstance();
        System.out.println("静态内部类 - 是否为同一实例: " + (static1 == static2));

        // 测试枚举
        SingletonEnum enum1 = SingletonEnum.INSTANCE;
        SingletonEnum enum2 = SingletonEnum.INSTANCE;
        System.out.println("枚举 - 是否为同一实例: " + (enum1 == enum2));
        enum1.doSomething();
    }
}
